﻿//-----------------------------------------------------------------------
// <copyright file="NodeExists.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Steve Overall</author>
// <email>v-stevov</email>
// <date>2005-04-15</date>
// <summary>Indicates whether the specified Node exists in the XML file.</summary>
//-----------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.XmlFile
{
	#region Using directives
	using System;
	using System.Collections.Generic;
	using System.Text;
	using System.Xml;

	using Microsoft.Build.Framework;
	using Microsoft.Build.Tasks;
	using Microsoft.Build.Utilities;

	using Microsoft.Sdc.Tasks;
	#endregion

	#region class comments
	/// <summary>
	/// Gets whether there are any nodes matching the specified XPath expression
	/// within the specified XML file.
	/// </summary>
	/// <remarks>
	/// <code>
	/// <![CDATA[<XmlFile.NodeExists Path="path" XPath="xpath" Namespaces="namespaces"/>]]>
	/// </code>
	/// <para>where:</para>
	/// <para><i>Path (Required)</i></para>
	/// <para>The path of the XML file to read.</para>
	/// <para><i>XPath (Required)</i></para>
	/// <para>The XPath expression to evaluate to search for the specified Node(s).</para>
	/// <para><i>Namespaces</i></para>
	/// <para>
	/// Optional TaskItems array detailing each of the namespace declarations required to read/maintain the target document.
	/// Each TaskItem should have 2 elements &lt;Prefix&gt; and &lt;Uri&gt;.
	/// </para>
	/// <para><i>Value (Output)</i></para>
	/// <para>True, at least one match for the XPath has been found.  False, no matches found.</para>
	/// <para><i>Count (Output)</i></para>
	/// <para>The number of matches found for the XPath expression.</para>
	/// </remarks>
	/// <example>
	/// <code><![CDATA[
	/// <Project>
	///     <Target Name="Test" >
	///         <XmlFile.NodeExists 
	///					Path="c:\app.config"
	///					XPath="/configuration/appSettings/add[@key='myKey']"
	///					Namespaces="@(ConfigNamespaces)">
	///				<Output TaskParameter="Value" Property="appSettings.myKey.exists"/>
	///			</XmlFile.NodeExists>
	///     </Target>
	/// </Project>
	/// ]]></code>    
	/// </example>
	#endregion
	public class NodeExists : BaseXmlFileTask
	{
		#region private declarations
		private bool				_value				= false;
		private int					_count				= 0;
		#endregion

		#region constructors
		/// <summary>
		/// Create a new ChangeCount.
		/// </summary>
		public NodeExists() : base()
		{
		}
		#endregion

		#region override of InternalExecute
		/// <summary>
		/// Carry out this task's action.
		/// </summary>
		protected override void InternalExecute()
		{
			//	Load the XML file.
			XmlDocument xmlDoc = this.OpenXmlFile( this.Path );
			XmlNamespaceManager nsMgr = this.GetNamespaceManagerForDoc( xmlDoc, this.Namespaces );

			//	Run the XPath Expression against the XML file.
			//	See if we find any matching nodes.
			XmlNodeList nodes = xmlDoc.SelectNodes( this.XPath, nsMgr );
			_count = ( nodes != null ? nodes.Count : 0 );
			_value = ( _count > 0 );

			Log.LogMessageFromResources( "XmlFile.NodeExists.Success", this.FileName, _count, this.XPath );
		}
		#endregion

		#region public Properties
		/// <summary>
		/// The number of matches for the XPath Expression found.
		/// </summary>
		/// <value>The number of matches for the XPath Expression found.</value>
		[Output]
		public int Count
		{
			get { return _count; }
		}

		/// <summary>
		/// Indicates whether any matches for the XPath Expression have been found, or not.
		/// </summary>
		/// <value>Indicates whether any matches for the XPath Expression have been found, or not.</value>
		[Output]
		public bool Value
		{
			get { return _value; }
		}
		#endregion
	}
}
